package org.hades.corelib.utils.device

import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.graphics.drawable.Drawable
import android.media.ExifInterface
import android.text.TextUtils
import androidx.annotation.IntRange
import androidx.core.graphics.drawable.DrawableCompat
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import kotlin.math.max
import kotlin.math.min


/**
 *
 */
object DrawableUtils {
    var DEF_OUTPUT_SIZE: Size = Size(1920, 1080)

    /**
     * 为图片添加一层tint
     *
     * @param drawable
     * @param colorStateList
     * @return
     */
    fun tintDrawable(drawable: Drawable, colorStateList: ColorStateList?): Drawable {
        val wrappedDrawable: Drawable = DrawableCompat.wrap(drawable.mutate())
        DrawableCompat.setTintList(wrappedDrawable, colorStateList)
        return wrappedDrawable
    }

    /**
     * 测量
     *
     * @param path
     * @return
     */
    fun measureSize(path: String?): Size? {
        if (TextUtils.isEmpty(path)) return null
        val options: BitmapFactory.Options = BitmapFactory.Options()
        //只会返回这个bitmap的尺寸
        options.inJustDecodeBounds = true
        BitmapFactory.decodeFile(path, options)
        val height: Int = options.outHeight
        val width: Int = options.outWidth
        return Size(width, height)
    }

    fun measureSampleSize(bitMapSize: Size?, outSize: Size?): Int {
        var sampleSize = 1
        if (bitMapSize == null || outSize == null) return sampleSize
        var min: Int = min(
            bitMapSize.height / outSize.height,
            bitMapSize.width / outSize.width
        )
        while (min > 2) {
            min /= 2
            sampleSize *= 2
        }
        return sampleSize
    }

    private fun rotateBitmap(path: String?, scaledBitmap: Bitmap): Bitmap {
        var scaledBitmap: Bitmap = scaledBitmap
        var orientation = 0
        try {
            val exif = ExifInterface(path!!)
            orientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION, 0
            )
        } catch (e: IOException) {
            e.printStackTrace()
        }
        val matrix = Matrix()
        when {
            ExifInterface.ORIENTATION_ROTATE_90 === orientation -> {
                matrix.postRotate(90F)
            }
            ExifInterface.ORIENTATION_ROTATE_180 === orientation -> {
                matrix.postRotate(180F)
            }
            ExifInterface.ORIENTATION_ROTATE_270 === orientation -> {
                matrix.postRotate(270F)
            }
        }
        scaledBitmap = Bitmap.createBitmap(
            scaledBitmap, 0, 0,
            scaledBitmap.width, scaledBitmap.height, matrix, true
        )
        return scaledBitmap
    }

    /**
     * 质量压缩
     *
     * @param bitmap
     * @param maxSize 最大输出size
     * @return
     */
    fun compressByQuality(bitmap: Bitmap?, maxSize: Long): ByteArray {
        return compressByQuality(bitmap, maxSize, 80)
    }

    fun compressByQuality(
        bitmap: Bitmap?,
        maxSize: Long,
        @IntRange(from = 50, to = 100)quality:Int
    ): ByteArray {
        val baos = ByteArrayOutputStream()
        var options_ = quality
        bitmap?.compress(Bitmap.CompressFormat.JPEG, options_, baos)
        while (baos.size() > maxSize) {
            baos.reset()
            options_ = max(0, options_ - 10)
            bitmap?.compress(Bitmap.CompressFormat.JPEG, options_, baos)
            if (options_ <= 60) break
        }
        return baos.toByteArray()
    }

    fun compressByScale(path: String?): Bitmap? {
        return compressByScale(path, DEF_OUTPUT_SIZE)
    }

    /**
     * 尺寸压缩
     *
     * @param path
     * @param outSize
     * @return
     */
    fun compressByScale(path: String?, outSize: Size): Bitmap? {
        val options: BitmapFactory.Options = BitmapFactory.Options()
        val bitMapSize: Size = measureSize(path) ?: return null
        val min = measureSampleSize(bitMapSize, outSize)
        var actualOutWidth: Int = bitMapSize.width
        var actualOutHeight: Int = bitMapSize.height
        if (min > 1) {
            actualOutWidth /= min
            actualOutHeight /= min
        }
        options.inSampleSize = min
        options.inJustDecodeBounds = false
        val sampleBitmap: Bitmap = BitmapFactory.decodeFile(path, options) ?: return null
        val scale = min(
            actualOutHeight.toDouble() / outSize.height.toDouble(),
            actualOutWidth.toDouble() / outSize.width.toDouble()
        )
        var scaledBitmap: Bitmap = Bitmap.createScaledBitmap(
            sampleBitmap,
            (actualOutWidth / scale).toInt(),
            (actualOutHeight / scale).toInt(), true
        )
        if (!sampleBitmap.equals(scaledBitmap)) sampleBitmap.recycle()
        scaledBitmap = rotateBitmap(path, scaledBitmap)
        return scaledBitmap
    }

    fun compress(path: String?, size: Int): ByteArray {
        val bitmap: Bitmap? = compressByScale(path)
        return compressByQuality(bitmap, size.toLong())
    }

    /**
     * 压缩并放入临时路径
     *
     * @param path    输入路径
     * @param maxByte 最大尺寸
     * @return 压缩过后的image path
     * @throws IOException
     */
    @Throws(IOException::class)
    fun compressToImageFile(path: String?, maxByte: Int): String {
        val file: File? = FileUtils.provideImageStampFile()
        val stream = FileOutputStream(file)
        stream.write(compress(path, maxByte))
        stream.close()
        assert(file != null)
        if (file != null) {
            return file.absolutePath
        }
        return ""
    }
}